#!/usr/bin/env jruby
# -*- coding: us-ascii -*-
# Elizabeth Wiethoff 2008

require 'java'
require 'test/unit'
dir = File.dirname(__FILE__)
require File.join(dir, '..', '..', 'lib', 'monkey', 'numeric2number')

########################################

module Constants4Numeric2NumberTests
  STRING = 'hello'
  HASHTABLE = java.util.Hashtable.new
  
  RI_SML = 5
  RI_MED = 123456789
  RI_BIG = 987654321123456789987654321123456789
  
  JBYTE = java.lang.Byte.new 5
  JSHORT = java.lang.Short.new 5
  JINTEGER = java.lang.Integer.new 123456789
  JLONG = java.lang.Long.new 123456789
  JBIGINTEGER = java.math.BigInteger.new RI_BIG.to_s
  
  JFLOAT = java.lang.Float.new 123456789
  JDOUBLE = java.lang.Double.new 123456789
  JBIGDECIMAL = java.math.BigDecimal.new RI_BIG.to_s
  
  S_BIG_REAL = '987654321123456789.987654321123456789'
  
  RF_SML = 5.7
  RF_MED = 12345.6789
  RF_BIG = S_BIG_REAL.to_f  # 9.8765432112345677e+17
  
  JFLOAT2 = java.lang.Float.new 5.7
  JDOUBLE2 = java.lang.Double.new 12345.6789
  JBIGDECIMAL2 = java.math.BigDecimal.new S_BIG_REAL
end

########################################

class TestRubyIntegerToJava < Test::Unit::TestCase
  include Constants4Numeric2NumberTests
  
  def test_should_create_Long
    assert_kind_of Java::JavaLang::Long, RI_SML.to_java, 's'
    assert_kind_of Java::JavaLang::Long, RI_MED.to_java, 'm'
  end
  
  def test_should_reject_big_value
    assert_raise(RangeError) { RI_BIG.to_java }
  end
  
  def test_should_produce_correct_value
    assert_equal RI_SML, RI_SML.to_java.long_value
    assert_equal RI_MED, RI_MED.to_java.long_value
  end
end

########################################

class TestRubyIntegerToBig < Test::Unit::TestCase
  include Constants4Numeric2NumberTests
  
  def test_should_create_BigInteger
    assert_kind_of Java::JavaMath::BigInteger, RI_SML.to_big, 's'
    assert_kind_of Java::JavaMath::BigInteger, RI_MED.to_big, 'm'
    assert_kind_of Java::JavaMath::BigInteger, RI_BIG.to_big, 'b'
  end
  
  def test_should_produce_correct_value
    assert_equal RI_SML.to_s, RI_SML.to_big.to_string
    assert_equal RI_BIG.to_s, RI_BIG.to_big.to_string
  end
end

########################################

class TestRubyIntegerFromJava < Test::Unit::TestCase
  include Constants4Numeric2NumberTests
  
  def test_should_accept_java_Number
    Hash[
      'b', JBYTE, 's', JSHORT, 'i', JINTEGER, 'l', JLONG, 
      'bi', JBIGINTEGER, 'f', JFLOAT, 'd', JDOUBLE, 'bd', JBIGDECIMAL
    ].each_pair do |msg, x|
      assert_nothing_raised(msg) { Integer.from_java(x) }
    end
  end
  
  def test_should_reject_others
    assert_raise(TypeError, 's') { Integer.from_java(STRING) }
    assert_raise(TypeError, 'h') { Integer.from_java(HASHTABLE) }
    assert_raise(TypeError, 'r') { Integer.from_java(RI_MED) }
  end
  
  def test_should_produce_correct_value_from_integer
    assert_equal RI_SML, Integer.from_java(JBYTE)
    assert_equal RI_SML, Integer.from_java(JSHORT)
    assert_equal RI_MED, Integer.from_java(JINTEGER)
    assert_equal RI_MED, Integer.from_java(JLONG)
    assert_equal RI_BIG, Integer.from_java(JBIGINTEGER)
  end
  
  def test_should_truncate_factional_part
    [
      [java.lang.Float, 1.7, 1], 
      [java.lang.Double, 1.7, 1], 
      [java.math.BigDecimal, '1.7', 1], 
      [java.lang.Float, -1.7, -1], 
      [java.lang.Double, -1.7, -1], 
      [java.math.BigDecimal, '-1.7', -1], 
    ].each do |type, x, expected|
      assert_equal expected, Integer.from_java(type.new(x))
    end
  end
end

########################################

class TestRubyFloatToJava < Test::Unit::TestCase
  include Constants4Numeric2NumberTests
  
  def test_should_create_Double
    assert_kind_of Java::JavaLang::Double, RF_SML.to_java, 's'
    assert_kind_of Java::JavaLang::Double, RF_BIG.to_java, 'b'
  end
  
  def test_should_produce_correct_value
    assert_equal RF_SML, RF_SML.to_java.double_value
    assert_equal RF_BIG, RF_BIG.to_java.double_value
  end
end

########################################

class TestRubyFloatToBig < Test::Unit::TestCase
  include Constants4Numeric2NumberTests
  
  def test_should_create_BigDecimal
    assert_kind_of Java::JavaMath::BigDecimal, RF_SML.to_big, 's'
    assert_kind_of Java::JavaMath::BigDecimal, RF_MED.to_big, 'm'
    assert_kind_of Java::JavaMath::BigDecimal, RF_BIG.to_big, 'b'
  end
  
  def test_should_produce_correct_value
    fmt = '%0.6e'
    assert_equal format(fmt, RF_SML), 
      format(fmt, RF_SML.to_big.float_value)
    assert_equal format(fmt, RF_BIG), 
      format(fmt, RF_BIG.to_big.float_value)
  end
end

########################################

class TestRubyFloatFromJava < Test::Unit::TestCase
  include Constants4Numeric2NumberTests
  
  def test_should_accept_java_Number
    Hash[
      'b', JBYTE, 's', JSHORT, 'i', JINTEGER, 'l', JLONG, 
      'bi', JBIGINTEGER, 'f', JFLOAT2, 'd', JDOUBLE2, 'bd', JBIGDECIMAL2
    ].each_pair do |msg, x|
      assert_nothing_raised(msg) { Float.from_java(x) }
    end
  end
  
  def test_should_reject_others
    assert_raise(TypeError, 's') { Float.from_java(STRING) }
    assert_raise(TypeError, 'h') { Float.from_java(HASHTABLE) }
    assert_raise(TypeError, 'r') { Float.from_java(RI_MED) }
  end
  
  def test_should_produce_correct_value_from_integer
    assert_equal RI_SML, Float.from_java(JBYTE)
    assert_equal RI_SML, Float.from_java(JSHORT)
    assert_equal RI_MED, Float.from_java(JINTEGER)
    assert_equal RI_MED, Float.from_java(JLONG)
    assert_equal RI_BIG, Float.from_java(JBIGINTEGER)
  end
  
  def test_should_produce_correct_value_from_float
    fmt = '%0.6e'
    assert_equal format(fmt, RF_SML), 
      format(fmt, Float.from_java(JFLOAT2))
    assert_equal format(fmt, RF_MED), 
      format(fmt, Float.from_java(JDOUBLE2))
    assert_equal format(fmt, RF_BIG), 
      format(fmt, Float.from_java(JBIGDECIMAL2))
  end
end
